#include "parser.h"
#include <iomanip>
#include <iostream>
#include <sstream>

Parser::Parser()
{
}

Parser::Parser(string input)
{
    for (int i = 0; i < input.size(); i++)
    {
        if (input[i] != 'n')
        {
            letters.push(string(1, input[i]));
        }
        else
        {
            char tmp[3] = {input[i] , input[i+1], input[i+2]};
            letters.push(string(tmp));
            i = i + 2;
        }     
    } 
    letters.push("$");
}

bool Parser::reduce(string action)
{
    int exp_num = stoi(action.substr(1));
    switch (exp_num)
    {
    //E->E+T
    case 1:

    //E->E-T    
    case 2:
        //pop出3个元素
		state.pop();
		state.pop();
		state.pop();
		symbol.pop();
		symbol.pop();
		symbol.pop();
        //将当前元素push进去
        symbol.push("E");
        if (goto_table[state.top()][0] == -1)
        {
            return false;
        }
        state.push(goto_table[state.top()][0]);
        break;

    //E->T    
    case 3:
        //pop出1个元素
		state.pop();
		symbol.pop();
		//将当前元素push进去
		symbol.push("E");
		if(goto_table[state.top()][0]==-1) {
			return false;
		}
		state.push(goto_table[state.top()][0]);
        break;
    
    //T->T*F
    case 4:
           
    //T->T/F
    case 5:
        //pop出3个元素
		state.pop();
		state.pop();
		state.pop();
		symbol.pop();
		symbol.pop();
		symbol.pop();
		//将当前元素push进去
		symbol.push("T");
        if(goto_table[state.top()][1]==-1) {
			return false;
		}
		state.push(goto_table[state.top()][1]);
        break;

    //T->F
    case 6:
        //pop出1个元素
		state.pop();
		symbol.pop();
		//将当前元素push进去
		symbol.push("T");
		if(goto_table[state.top()][1]==-1) {
			return false;
		}
		state.push(goto_table[state.top()][1]);
        break;
    
    //F->(E)
    case 7:
        //pop出3个元素
        state.pop();
		state.pop();
		state.pop();
		symbol.pop();
		symbol.pop();
		symbol.pop();
		//将当前元素push进去
		symbol.push("F");
		if(goto_table[state.top()][2]==-1) {
			return false;
		}
		state.push(goto_table[state.top()][2]);
        break;
    
    //F->num
    case 8:
        //pop出1个元素
		state.pop();
		symbol.pop();
		//将当前元素push进去
		symbol.push("F");
		if(goto_table[state.top()][2]==-1) {
			return false;
		}
		state.push(goto_table[state.top()][2]);
        break;

    default:
        return false;
    }
    return true;
}

bool Parser::shift(string action)
{
    if (letters.size() > 0)
    {
        state.push(stoi(action.substr(1)));
	    symbol.push(letters.front());
        letters.pop();
        return true;
    }
    else
    {
        return false;
    }    
}

template<typename T> void Parser::printStack(stack<T> s)
{
    stack<T> tmp;
    stringstream stream;
    int length = s.size();
    for (int i = 0; i < length; i++)
    {
        tmp.push(s.top());
        s.pop();
    }

    stream << "[";
    
    for (int i = 0; i < length; i++)
    {
        T ele = tmp.top();
        tmp.pop();
        s.push(ele);
        stream  << ele << ", ";
    }
    stream << "]";
    cout << std::left << setw(30) << stream.str();
    return;  
}

void Parser::printQueue(queue<string> q)
{
    stringstream stream;
    int length = q.size();
    for (int i = 0; i < length; i++)
    {
        string str = q.front();
        q.pop();
        q.push(str);
        stream << str;
    }
    cout << std::left << setw(30) << stream.str();
    return;   
}

void Parser::printLine(string action)
{
    cout << step << "\t";
    printStack(state);
    cout << "\t";
    printStack(symbol);
    cout << "\t";
    printQueue(letters);
    if (action[0] == 'S')
    {
        cout << "\tshift " << action.substr(1) << endl;
    }
    else if (action[0] == 'R')
    {
        cout << "\treduce by " << expression[stoi(action.substr(1))] << endl;
    }
    else if (action == "ACC")
    {
        cout << "\tACC" << endl;
    }
       
}

int Parser::index(string str)
{
    for (int i = 0; i < 8; i++)
    {
        if (str == action_column[i])
        {
            return i;
        }       
    }
    return -1;  
}

void Parser::error()
{
    cout << "\n[Error]: error, step " << step << endl;
}

bool Parser::parse()
{
    step = 0;
    state.push(0);
    symbol.push("-");
    cout << "\n步骤";
    cout << std::left << setw(30) << "\t状态" ;
    cout << std::left << setw(30) << "\t符号" ;
    cout << std::left << setw(30) << "\t字符串";
    cout << "\t动作" << endl;
    while(!letters.empty())
    {
        step++;
        string str = letters.front();
        int cur_state = state.top();
        int column = index(str);
        if (column < 0)
        {
            error();
            return false;
        }       
        string action = action_table[cur_state][column];
        if (action == "")
        {
            error();
            return false;
        }
        printLine(action);
        if (action[0] == 'S')
        {
            shift(action);
        }
        else if (action[0] == 'R')
        {
            reduce(action);
        }else if (action == "ACC")
        {
            return true;
        }                
    }
    return false;
}